home *** CD-ROM | disk | FTP | other *** search
- /*********************************************************************\
- ** ________________________________ **
- ** A n t h o n y |________ __ __ ________| **
- ** | |o_| |o_| | **
- ** T h y s s e n __| __ __ |__ **
- ** __| __| | | |__ |__ **
- ** `` Dragon Computing ! '' __| __| | | |__ |__ **
- ** |_____| |__| |_____| **
- ** **
- \*********************************************************************/
-
- #include "AMenu.h"
- #include "AllocStr.h"
- #include <libraries/DosExtens.h> /* for Process definition */
- #include <Workbench/Startup.h> /* for WBStartup definition */
- #include <Workbench/WorkBench.h> /* for DiskObject definition */
- #include <Proto/Icon.h>
- #include <string.h>
-
- extern struct Process *MyProc; /* This Process */
- extern BPTR WorkDirLock; /* The current directory */
-
- extern void Warn(char *); /* routine to notify user of error */
-
- /*-----------------------------------------------------*/
-
- static void
- RunCLI( EItem )
- struct ExtMenuItem *EItem;
- /* execute a CLI command using the appropiate console
- ** for command (either a default or commands own).
- */
- {
- struct ProcessControlBlock *PCB=NULL; /* structure for Arp's ASynchRun */
- BPTR NewDirLock=NULL; /* Directory Lock for CD */
- long CLI=0; /* result code - CLI number used */
- char buf[256], *ConWin, *Error;
-
- DB( FPrintf(DBWindow, "CLIRun -> `%s'\n", EItem->Cmd); )
-
- /* is new Directory Update the directory */
- if( EItem->Directory ) {
- if( !( NewDirLock = Lock(EItem->Directory, ACCESS_READ) ) ) {
- SPrintf(buf, "Unable to Find Directory `%s' ", EItem->Directory);
- Warn(buf); return;
- }
- CurrentDir(NewDirLock);
- }
-
-
- PCB = (struct ProcessControlBlock *)
- AllocMem( sizeof(struct ProcessControlBlock), MEMF_CLEAR|MEMF_PUBLIC);
-
- if( !PCB )
- CLI = PR_NOMEM; /* failed to allocate PCB struct */
- else {
- /* allocate appropiate stack and prioity */
- PCB->pcb_StackSize = EItem->Stack; /* Stack */
- PCB->pcb_Pri = EItem->Pri; /* Pri */
-
- ConWin = ( EItem->Console ? EItem->Console : M->Console );
- switch( EItem->Mode ) {
- case 'C': /* CLI mode - Open a Console */
- PCB->pcb_Control = PRF_STDIO;
- PCB->pcb_Console.pcb_ConName = (BYTE *) ConWin;
- break;
- case 'R': /* RunBack - No File Handles */
- PCB->pcb_Control = PRF_SAVEIO;
- break;
- case 'S': /* Script - New Shell */
- PCB->pcb_Control = INTERACTIVE_SHELL;
- }
-
- DB( FPrintf(DBWindow, "-- ASynchRun()\n"); )
- CLI = ( EItem->Mode == 'S' )
- ? ASyncRun( ConWin, EItem->Cmd, PCB) /* interactive shell */
- : ASyncRun( EItem->Cmd, EItem->Args, PCB); /* run command */
- }
-
- /* Handle Errors */
- if( CLI<0 ) { /* negitive result -- Report Appropiate Error */
- switch( CLI ) {
- case PR_NOSTDIO: Error = "%s: Unable to open Console"; break;
- case PR_NOFILE: Error = "%s: Unknown Command `%s'"; break;
- case PR_NOMEM: Error = "%s: Not Enough Memory"; break;
- case PR_NOSLOT: Error = "%s: Task Table Full"; break;
- case PR_NOINPUT:
- case PR_NOOUTPUT: Error = "%s: IO Error on Console"; break;
- case PR_SCRIPT: Error = "%s: Script run using wrong mode"; break;
- default: Error = "%s: ASynchRun Failed on `%s' (%ld)";
- }
- SPrintf(buf, Error, VERSION, EItem->Cmd, CLI);
- Warn(buf);
- }
-
- if( PCB )
- FreeMem( PCB, sizeof(struct ProcessControlBlock) );
- if( EItem->Directory ) /* Return to the Working Directory */
- UnLock( CurrentDir( WorkDirLock ) );
- DB( FPrintf(DBWindow, "---- Done ----\n"); )
- }
-
-
- /*--------------------------------------------------*/
- /* procedures to support running WorkBench programs */
-
-
- extern WBProcesses; /* WB processes currently running */
- extern struct MsgPort *WBReplyPort; /* Port for Process to reply to */
-
-
- void
- WBFree( StartMsg )
- struct WBStartup *StartMsg;
- /* Free up space used by a workbench startup message. Called whenever
- * a workbench program replies to the startup message, and whenever
- * `WBRun()' gets an error
- */
- {
- register int i;
-
- if( StartMsg ) {
- if( WBProcesses ) /* decrement number of processes */
- WBProcesses--;
- if( StartMsg->sm_ArgList ) {
- for (i=0; i<StartMsg->sm_NumArgs; i++) {
- if( StartMsg->sm_ArgList[i].wa_Lock )
- UnLock(StartMsg->sm_ArgList[i].wa_Lock);
- if( StartMsg->sm_ArgList[i].wa_Name )
- FreeStr(StartMsg->sm_ArgList[i].wa_Name);
- }
- FreeMem( StartMsg->sm_ArgList,
- sizeof(struct WBArg) *StartMsg->sm_NumArgs );
- }
- if( StartMsg->sm_Segment )
- UnLoadSeg(StartMsg->sm_Segment);
- if( StartMsg->sm_ToolWindow )
- FreeStr(StartMsg->sm_ToolWindow );
- FreeMem( StartMsg , sizeof(struct WBStartup) );
- }
- }
-
-
- static void
- RunWB( EItem )
- struct ExtMenuItem *EItem;
- /* load and run a workbench program
- * This routine is errored in the following ways
- * 1/ No ToolTypes are handled
- * 2/ The TOOL for a PROJECT is expected to have an icon (it may not!).
- * 3/ Current Directory is that of the TOOL not the PROJECT or
- * 4/ User can't select the Current Directory to use (should he?).
- * -- Anthony Thyssen
- */
- {
- BPTR DirLock = NULL, OldLock = NULL, IconLock;
- struct WBStartup *StartMsg = NULL;
- struct DiskObject *DiskObject = NULL;
- char *Name, buf[128];
- BOOL Error = TRUE; /* assume the worst */
- int I;
-
- /* Lock Projects Directory */
- Name = BaseName(EItem->Cmd);
- strcpy(buf, EItem->Cmd);
- strcat(buf, ".info"); /* this will be present the project may not! */
- if( !(IconLock = Lock(buf, ACCESS_READ) ) ) {
- SPrintf(buf, "Can't locate `%s.info'", Name);
- goto finish;
- }
- DirLock = ParentDir(IconLock);
- UnLock(IconLock);
- if( !DirLock ) {
- SPrintf(buf, "Directory invalid for `%s'", EItem->Cmd);
- goto finish;
- }
-
- /* Load Icon */
- OldLock = CurrentDir( DirLock );
- if( !(DiskObject = GetDiskObject(Name)) ) {
- SPrintf(buf, "Can't locate `%s.info'", Name);
- goto finish;
- }
- switch( DiskObject->do_Type ) {
- case WBTOOL: I=1; break; /* just the tool */
- case WBPROJECT: I=2; break; /* tool & project */
- default:
- SPrintf(buf, "`%s.info' is not a TOOL or PROJECT!", Name);
- goto finish;
- }
-
- /* allocate the startup message */
- if( !(StartMsg = (struct WBStartup *)
- AllocMem( sizeof(struct WBStartup), MEMF_PUBLIC|MEMF_CLEAR))) {
- SPrintf(buf, "%s: Not Enough Memory", VERSION);
- goto finish;
- }
- StartMsg->sm_NumArgs = I;
- if( !(StartMsg->sm_ArgList = (struct WBArg *)
- AllocMem( sizeof(struct WBArg)*I, MEMF_PUBLIC|MEMF_CLEAR)) ) {
- SPrintf(buf, "%s: Not Enough Memory", VERSION);
- goto finish;
- }
-
- I--; /* Fill in the Last WBArg the TOOL/Project we referenced */
- StartMsg->sm_ArgList[I].wa_Lock = DirLock;
- StartMsg->sm_ArgList[I].wa_Name = AllocStr(Name);
-
- if( I ) { /* if WBPROJECT - Fill out the Tool */
- StartMsg->sm_ArgList->wa_Lock = DupLock(DirLock); /* same as project */
- StartMsg->sm_ArgList->wa_Name = AllocStr(DiskObject->do_DefaultTool);
- Name = StartMsg->sm_ArgList->wa_Name; /* Set the new name */
- }
-
- /* initialize rest of startup message */
- StartMsg->sm_Message.mn_ReplyPort = WBReplyPort;
- StartMsg->sm_Message.mn_Length = sizeof(struct WBStartup);
- StartMsg->sm_Message.mn_Node.ln_Type = NT_MESSAGE;
- StartMsg->sm_ToolWindow = AllocStr(DiskObject->do_ToolWindow);
-
- /* Insure a decent stack size, some progs have this set to zero */
- if( DiskObject->do_StackSize < EItem->Stack )
- DiskObject->do_StackSize = EItem->Stack;
-
-
- /* load in the program */
- if( !(StartMsg->sm_Segment = LoadPrg(Name)) ) {
- SPrintf(buf, "Unable to Load `%s'", Name);
- goto finish;
- }
-
- /* create process */
- if( !(StartMsg->sm_Process = CreateProc( Name, (LONG)EItem->Pri,
- StartMsg->sm_Segment, DiskObject->do_StackSize)) ) {
- SPrintf(buf, "Can't execute `%s'", Name);
- goto finish;
- }
-
- /* everything's ok -- start 'er up */
- PutMsg( StartMsg->sm_Process , (struct Message *)StartMsg );
- Error = FALSE;
- WBProcesses++; /* keep track of unreplied startup messages */
-
- finish:
- if( DiskObject ) FreeDiskObject( DiskObject );
- if( OldLock ) CurrentDir( OldLock );
- if( Error ) {
- if( StartMsg ) WBFree( StartMsg );
- Warn(buf);
- }
- }
-
-
- /*-------------------------------------------------*/
-
- void
- RunItem( EItem )
- struct ExtMenuItem *EItem;
- {
- switch( EItem->Mode ) {
- case 'R':
- case 'C':
- case 'S': RunCLI( EItem ); break;
- case 'W': RunWB( EItem ); break;
- }
- }
-
-